﻿using System;
using System.Threading.Tasks;
using K9Nano.MultiTenancy;
using Microsoft.Extensions.Options;
using MySql.Data.MySqlClient;

namespace K9Nano.MySql
{
    public class MySqlTenantStore : ITenantStore
    {
        protected readonly ITenantCache Cache;
        protected readonly MySqlOption Option;

        public MySqlTenantStore(ITenantCache cache, IOptionsMonitor<MySqlOption> optionsMonitor)
        {
            Cache = cache;
            Option = optionsMonitor.CurrentValue;
        }

        public virtual TenantInfo Find(Guid tenantId)
        {
            var tenantName = Cache.Get(tenantId);
            if (tenantName == null)
            {
                using var connection = new MySqlConnection(Option.ConnectionString);
                using var cmd = connection.CreateCommand();
                cmd.CommandText = "select Name from app_tenant where Id=@id and IsActive=1";
                cmd.Parameters.Add(new MySqlParameter("@id", tenantId));
                connection.Open();
                var reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    tenantName = (string)reader["Name"];
                    var result = new TenantInfo(tenantId, tenantName);
                    Cache.Set(result);
                    return result;
                }

                return null;
            }

            return new TenantInfo(tenantId, tenantName);
        }

        public virtual TenantInfo Find(string tenancyName)
        {
            var tenantId = Cache.Get(tenancyName);
            if (tenantId == default)
            {
                using var connection = new MySqlConnection(Option.ConnectionString);
                using var cmd = connection.CreateCommand();
                cmd.CommandText = "select Id from app_tenant where Name=@name and IsActive=1";
                cmd.Parameters.Add(new MySqlParameter("@name", tenancyName));
                connection.Open();
                var reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    tenantId =  Guid.Parse(reader["Id"].ToString());
                    var result = new TenantInfo(tenantId, tenancyName);
                    Cache.Set(result);
                    return result;
                }

                return null;
            }

            return new TenantInfo(tenantId, tenancyName);
        }

        public virtual async ValueTask<TenantInfo> FindAsync(Guid tenantId)
        {
            var tenantName = Cache.Get(tenantId);
            if (tenantName == null)
            {
                await using var connection = new MySqlConnection(Option.ConnectionString);
                await using var cmd = connection.CreateCommand();
                cmd.CommandText = "select Name from app_tenant where Id=@id and IsActive=1";
                cmd.Parameters.Add(new MySqlParameter("@id", tenantId));
                await connection.OpenAsync();
                var reader = cmd.ExecuteReader();
                if (await reader.ReadAsync())
                {
                    tenantName = (string)reader["Name"];
                    var result = new TenantInfo(tenantId, tenantName);
                    Cache.Set(result);
                    return result;
                }

                return null;
            }

            return new TenantInfo(tenantId, tenantName); ;
        }

        public virtual async ValueTask<TenantInfo> FindAsync(string tenancyName)
        {
            var tenantId = Cache.Get(tenancyName);
            if (tenantId == default)
            {
                await using var connection = new MySqlConnection(Option.ConnectionString);
                await using var cmd = connection.CreateCommand();
                cmd.CommandText = "select Id from app_tenant where Name=@name and IsActive=1";
                cmd.Parameters.Add(new MySqlParameter("@name", tenancyName));
                await connection.OpenAsync();
                var reader = cmd.ExecuteReader();
                if (await reader.ReadAsync())
                {
                    tenantId = Guid.Parse(reader["Id"].ToString());
                    var result = new TenantInfo(tenantId, tenancyName);
                    Cache.Set(result);
                    return result;
                }

                return null;
            }

            return new TenantInfo(tenantId, tenancyName); 
        }
    }
}